//
//  cardStack.c
//  Testat_5
//
//  Created by Benno Lauther on 20.11.13.
//
//
#include <stdio.h>
#include "cardStack.h"
#include "printCard.h"
#include <time.h>
#include <stdlib.h>


/***************************************************************************************
 FUNCTION    :  numberOfCardsInStack
 PURPOSE     :  counts the cards in a certain stack
 
 INPUT       :  - Pointer to the card stack that shall be counted
 
 OUTPUT      :  - Number of cards in the given stack
 
 written by Benno Lauther
 ***************************************************************************************/
int numberOfCardsInStack(int (*stack)[NR_CARDS])
{
    int i = 0;
    while( (*stack)[i] != NO_CARD && i < NR_CARDS)
    {
        //DONOTHING
        i++;
    }
    
    return i;
}



/***************************************************************************************
 FUNCTION    :  stackIsEmpty
 PURPOSE     :  checks if a certain stack contains any elements. Faster than 
                numberOfCardsInStack
 
 INPUT       :  - Pointer to the card stack that shall be checked
 
 OUTPUT      :  - 1 if empty
                - 0 if not empty
 
 written by Benno Lauther
 ***************************************************************************************/
int stackIsEmpty(int (*stack)[NR_CARDS])
{
    if((*stack)[0] == NO_CARD)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}


/***************************************************************************************
 FUNCTION    :  stackContainsEnoughCardsForNextTurn
 PURPOSE     :  checks if there are at least NR_CARDS_DRAWN_WHEN_SEVEN cards in the stack
 
 INPUT       :  - Pointer to the card stack that shall be checked
 
 OUTPUT      :  - 1 if enough cards
                - 0 if not enough cards
 
 written by Benno Lauther
 ***************************************************************************************/
int stackContainsEnoughCardsForNextTurn(int (*stack) [NR_CARDS])
{
    if((*stack)[NR_CARDS_DRAWN_WHEN_SEVEN] != NO_CARD)
    {
        return 1;
    }
    else
    {
        return 0;
    }

}


/***************************************************************************************
 FUNCTION    :  addCardToStack
 PURPOSE     :  adds a card to a certain stack. If Order isn't of importance, use this
 function because of its higher performance. Else, use addCardToStackOnTop
 
 INPUT       :  - Pointer to the card stack the card shall be added to
 - The value of the card that shall be added
 OUTPUT      :  - Value of the card that was added
 
 written by Benno Lauther
 ***************************************************************************************/
int addCardToStack(int (*stack)[NR_CARDS],int cardToAdd)
{
    (*stack)[numberOfCardsInStack(stack)] = cardToAdd;
    return cardToAdd;
}


/***************************************************************************************
 FUNCTION    :  peekTopCardOfStack
 PURPOSE     :  returns the value of the top card of the given card stack
 
 INPUT       :  - Pointer to the card stack you want to peek
 
 OUTPUT      :  - Value of the top card
 
 written by Benno Lauther
 ***************************************************************************************/
int peekTopCardOfStack(int (*stack)[NR_CARDS])
{
    return (*stack)[numberOfCardsInStack(stack)-1];
}



/***************************************************************************************
 FUNCTION    :  removeCardAtPositionFromStack
 PURPOSE     :  removes the card at a certain position from the given card stack
 
 INPUT       :  - Pointer to the card stack the card shall be removed from
                - Position of the card you want to remove
 
 OUTPUT      :  - The value of the removed card
 
 written by Benno Lauther
 ***************************************************************************************/
int removeCardAtPositionFromStack(int (*stack)[NR_CARDS], int positionToRemove)
{
    int cardToRemove = (*stack)[positionToRemove];
    
    int i;
    for (i=positionToRemove; (*stack)[i+1]!=NO_CARD && i < NR_CARDS-1; i++ )
    {
        (*stack)[i] = (*stack)[i+1];
    }
    (*stack)[i] = NO_CARD;
    
    return cardToRemove;
}

/***************************************************************************************
 FUNCTION    :  removeTopCardFromStack
 PURPOSE     :  removes the top card from the given card stack
 
 INPUT       :  - Pointer to the card stack the card shall be removed from
 
 OUTPUT      :  - The value of the removed card
 
 written by Benno Lauther
 ***************************************************************************************/
int removeTopCardFromStack(int (*stack)[NR_CARDS])
{
    return removeCardAtPositionFromStack(stack, numberOfCardsInStack(stack)-1);
}


/***************************************************************************************
 FUNCTION    :  removeCardFromStack
 PURPOSE     :  removes the card with a certain value from the given card stack
 
 INPUT       :  - Pointer to the card stack the card shall be removed from
                - Value of the card you want to remove
 
 OUTPUT      :  - The value of the removed card
 
 written by Benno Lauther
 ***************************************************************************************/
int removeCardFromStack(int (*stack)[NR_CARDS], int cardToRemove)
{
    
    int i = 0;
    while ((*stack)[i]!=cardToRemove)
    {
        i++;
    }
    while ((*stack)[i+1]!=NO_CARD )
    {
        (*stack)[i] = (*stack)[i+1];
        i++;
    }
    (*stack)[i] = NO_CARD;
    
    return cardToRemove;
}

/***************************************************************************************
 FUNCTION    :  initStack
 PURPOSE     :  Marks a card stack as "empty", filling it up with NO_CARD items
 
 INPUT       :  - Pointer to the card stack to initialize
 
 OUTPUT      :  NONE
 
 written by Benno Lauther
 ***************************************************************************************/
void initStack(int (*stack)[NR_CARDS])
{
    for (int i = 0; i<NR_CARDS; i++)
    {
        (*stack)[i] = NO_CARD;
    }
}

/***************************************************************************************
FUNCTION    : findValidMove
PURPOSE     : Finds the next valid move in a stack of cards.
 
INPUT       : - Pointer to the card stack to search in (Integer Array of size NR_CARDS)
              - Value of the open card
 
OUTPUT      : - Number of first valid card found
              - NO_CARD if no move found
 
written by Benno Lauther
***************************************************************************************/
int findValidMove(int (*stack)[NR_CARDS],int openCard, int* colorWish)
{
  
    int i=0;

        while ( !validMove(openCard, (*stack)[i], *colorWish)  &&  i < NR_CARDS && (*stack)[i]!= NO_CARD)
        {
            i++;
        }
        

    
    if((*stack)[i]==NO_CARD || i == NR_CARDS)
    {
        return NO_CARD;         //No valid move found
    }
    else
    {
        *colorWish = NO_COLORWISH;
        //return (*stack)[i]; // Return move found
    	return i; // Return number of card in stack
    }
    
    
}


/***************************************************************************************
 FUNCTION    :  printCardStack
 PURPOSE     :  printsCardStack via function: printCard()
 
 INPUT       :  - Pointer to the card stack that shall be printed
 
 OUTPUT      :  void
                Console:
                0 - COLOR TYPE
                1 - COLOR TYPE
                2 - COLOR TYPE
 
 written by Benno Lauther
 ***************************************************************************************/
void printCardStack(int (*stack)[NR_CARDS])
{
    int count  = numberOfCardsInStack(stack);
    for (int i=0; i<count; i++)
    {
        printf("%2d: \t",i+1);
        printCard((*stack)[i]);
        putchar('\n');
    }
}




/***************************************************************************************
 FUNCTION    :  getDominantColorOfstack
 PURPOSE     :  looks for the most dominant color in a card stack. If multiple colors are
                equally dominant the first appearance is returned.
 
 INPUT       :  - Pointer to the card stack that shall be searched
 
 OUTPUT      :  - Most dominant color
 
 written by Benno Lauther
 ***************************************************************************************/
int getDominantColorOfstack( int (*stack)[NR_CARDS])
{
    int colors[NR_COLOURS];
    int dominantColor = NO_CARD;
    int buffer=0;
    for(int i= 0; i<NR_COLOURS;i++)
    {
        colors[i] = 0;
    }
    int stackSize = numberOfCardsInStack(stack);
    for(int i = 0; i<stackSize; i++)
    {
        colors[(*stack)[i]/ NR_TYPES] ++;
    }
    
    for (int i =0; i<NR_COLOURS; i++)
    {
        if(colors[i]>buffer)
        {
        buffer = colors[i];
        dominantColor = i;
        }
    }
    
    return dominantColor;
    
}

int recyclePlayedCards(int (*stack)[NR_CARDS], int (*playedCards)[NR_CARDS])
{
    
    int openCard = removeTopCardFromStack(playedCards);
    int playedCardsCount = numberOfCardsInStack(playedCards);
    int stackCount = numberOfCardsInStack(stack);
    int j;
    int k;
    
    if(NR_CARDS-stackCount < playedCardsCount)
    {
        return NO_CARD;
    }
    else
    {
    srand((unsigned int)time(NULL));  /* start random number generater */
    for (int i = playedCardsCount -1; i; i--) {
        j = rand() % (i + 1);  /* random variable modulo remaining cards */
        /* swap entries of fields i and j */
        k = (*playedCards)[i];
        (*playedCards)[i] = (*playedCards)[j];
        (*playedCards)[j] = k;
        
        }
        
        for (int i= stackCount, i1 = 0; i< stackCount+playedCardsCount;i++,i1++)
        {
            (*stack)[i] =(*playedCards)[i];
            (*playedCards)[i] = NO_CARD;
        }
        
        addCardToStack(playedCards, openCard);
        
        return 0;
    
    }
        
}

/***************************************************************************************
 FUNCTION    :  sortPlayersHand
 PURPOSE     :  Sorts hand of Player from lowest to highest card, separated by colors
 
 INPUT       :  - Pointer to players card stack
 
 OUTPUT      :  - void
 
 written by Tobias Stein
 ***************************************************************************************/
void sortPlayersHand(int (*stack)[NR_CARDS]){
	int i, j, k;
	for (i=1;(*stack)[i]!=NO_CARD;i++){
		j=(*stack)[i];
		k=i-1;
		while ((j<(*stack)[k])&&(k>=0)){
			(*stack)[k+1]=(*stack)[k];
			k--;
		}
		(*stack)[k+1] = j;
	}
}